CPP是如何变得更加Pythonic

1.前言

近年来,C ++发生了很大变化。最近的两个修订版本C ++ 11和C ++ 14引入了许多新功能,以Bjarne Stroustrup的话来说,“感觉就像是一种新语言。”

现代C ++赋予了一种全新的编程风格,不禁注意到它具有更多的Python风格。基于范围的循环,类型推导,向量和映射初始化器,lambda表达式。只要对C++的探索越多,就会发现借鉴Python的地方就越多。Python对现代C ++有直接影响吗?还是在C ++出现之前Python只是采用了一些有用的结构?我们一起来看看呗!

2.C++ VS Python不同

2.1常量

Python 在2008年引入了二进制文字。现在C++ 14中也开始添加了。

static const int primes = 0b10100000100010100010100010101100;

Python 在1998年还引入了原始字符串文字。在对正则表达式或Windows路径进行硬编码时,它们很方便。C ++ 11中做法就不同:

const char* path = R"(c:\\backslashes)";

2.2基于范围的循环

在Python中,for循环总是遍历Python对象:

for x in myList:

print(x)

同时,近三十年来,C ++仅支持C风格的for循环。最后,在C ++ 11中,添加了基于范围的for循环:

for (int x : myList)

std::cout << x;

您可以遍历std::vector实现begin和end成员函数的一个或任何类-与Python的iterator协议不同。使用基于范围的for循环,真心希望C ++ 也可以像Python一样内置函数xrange。

2.3弱化语言类型

Python一直是一种动态类型化的语言。无需声明变量类型,因为类型是对象本身的属性。

x = "Hello world!"

print(x)

另一方面,C ++不是动态输入的。它是静态类型的。但由于不是动态输入的。它是静态类型的。但由于自动类型推导,看起来就很像动态类型。

auto x = "Hello world!";

std::cout << x;

当调用几种类型重载的函数(例如std::ostream::operator<<或模板函数)时,C ++更类似于动态类型的语言。C ++ 14进一步完善了对auto关键字的支持,为lambda函数增加了对auto 返回值和auto 参数的支持。

2.4元组

从一开始Python就已经拥有了很多元组。当我们需要将多个值打包在一起时,一个类命名就够啦。

triple = (5, 6, 7)

print(triple[0])

C ++将元组添加到C ++ 11中的标准库中。该提案甚至提到了Python的灵感:

auto triple = std::make_tuple(5, 6, 7);

std::cout << std::get<0>(triple);

Python则可以将元组解压缩为单独的变量:

x, y, z = triple

我们可以使用C在C ++中执行相同的操作std::tie:

std::tie(x, y, z) = triple;

2.5统一初始化

在Python中,列表是内置类型。这样就可以使用单个表达式创建Python列表:

myList = [6, 3, 7, 8]

myList.append(5);

C++ std::vector是最接近Python列表的产物。统一初始化(C ++ 11中的新增功能)现在也使我们可以使用单个表达式来创建它们:

auto myList = std::vector{ 6, 3, 7, 8 };

myList.push_back(5);

在Python中,还可以使用单个表达式创建字典:

myDict = {5: "foo", 6: "bar"}

print(myDict[5])

同样,统一初始化也适用于C ++ std::map和unordered_map:

auto myDict = std::unordered_map{ { 5, "foo" }, { 6, "bar" } };

std::cout << myDict[5];

2.6Lambda表达式

自1994年以来,Python就一直支持lambda函数:

myList.sort(key = lambda x:abs(x))

Lambda表达式在C ++ 11中添加:

std::sort(myList.begin(), myList.end(), [](int x, int y){ return std::abs(x) < std::abs(y); });

在2001年,Python添加了静态嵌套范围,该范围允许lambda函数捕获在函数内部中定义的变量:

def adder(amount):

return lambda x: x + amount

...

print(adder(5)(5))

同样,C ++ lambda表达式支持一组灵活的捕获规则,使您可以执行类似的操作:

auto adder(int amount) {

return [=](int x){ return x + amount; };

}

...

std::cout << adder(5)(5);

2.7标准算法库

Python的内置filter函数可以让我们有选择地从列表中复制元素(尽管最好使用列表理解):

result = filter(lambda x: x >= 0, myList)

C ++ 11 引入了 std::copy_if,它使我们能够使用相似的,几乎功能的样式:

auto result = std::vector{};

std::copy_if(myList.begin(), myList.end(), std::back_inserter(result), [](int x){ return x >= 0; });

其他C ++ 算法模拟Python的内置插件包括transform,any_of,all_of,min和max。即将发布的范围提案有可能进一步简化此类表达。

2.8参数列表

Python从1998年开始支持任意参数列表。您可以定义一个函数,该函数接受可变数量的参数(以元组形式显示),并在将参数传递给另一个函数时扩展元组:

def foo(*args):

return tuple(*args)

...

triple = foo(5, 6, 7)

C ++ 11增加了对参数包的支持。与C风格的变量参数不同,但与Python的任意参数列表一样,参数包的名称表示整个参数序列。一个重要的区别:C ++参数包在运行时不会作为单个对象公开。但只有在编译时通过模板元编程来操作它们。

template auto foo(T&&... args) {

return std::make_tuple(args...);

}

...

auto triple = foo(5, 6, 7);

3.总结

并非所有新的C++ 11和C++ 14功能都模仿Python功能。Python被认为是一种友好的,易于接近的编程语言。也许它的一些魅力消失了?你怎么看?

本页共115段,3993个字符,6390 Byte(字节)